package cn.saltybe.analysis.util;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;

@Component
public class RemoteExecute {
    private final static String DEFAULT_CHARSET = "utf-8";
    private Connection connection;
    private static String address;
    private static String port;
    private static String username;
    private static String password;

    public static volatile RemoteExecute instance;

    @Value("${server.ssh.address}")
    public void setAddress(String address) {
        this.address = address;
    }

    public String getPort() {
        if (NumberUtils.isNumeric(this.port)) return port;
        return "22";
    }

    @Value("${server.ssh.port}")
    public void setPort(String port) {
        this.port = port;
    }

    public String getUsername() {
        if (this.username == null || this.username.length() == 0) return "root";
        return username;
    }

    @Value("${server.ssh.username}")
    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        if (this.password == null || this.password.length() == 0) return "";
        return password;
    }

    @Value("${server.ssh.password}")
    public void setPassword(String password) {
        this.password = password;
    }

    public static RemoteExecute getInstance() {
        if (instance == null) synchronized (RemoteExecute.class) {
            if (instance == null) instance = new RemoteExecute();
        }
        return instance;
    }

    public boolean login() {
        boolean flag = false;
        try {
            connection = new Connection(this.getAddress(), Integer.parseInt(this.getPort()));
            connection.connect();
            flag = connection.authenticateWithPassword(this.getUsername(), this.getPassword());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return flag;
    }

    private String processStdout(InputStream in, String charset) {
        InputStream stdout = new StreamGobbler(in);
        StringBuffer buffer = new StringBuffer();
        ;
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(stdout, charset));
            String line = null;
            while ((line = br.readLine()) != null) {
                buffer.append(line + "\n");
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer.toString();
    }

    public String execute(String cmd) {
        String result = "";
        try {
            if (login()) {
                Session session = connection.openSession();
                session.execCommand(cmd);
                result = processStdout(session.getStdout(), DEFAULT_CHARSET);
                if (StringUtils.isBlank(result)) {
                    result = processStdout(session.getStderr(), DEFAULT_CHARSET);
                }
                connection.close();
                session.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    public String executeSuccess(String cmd) {
        String result = "";
        try {
            if (login()) {
                Session session = connection.openSession();
                session.execCommand(cmd);
                result = processStdout(session.getStdout(), DEFAULT_CHARSET);
                connection.close();
                session.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    public String getAddress() {
        if (this.address == null || this.address.length() == 0) return "127.0.0.1";
        return address;
    }
}
